#ifndef __OLED_H
#define __OLED_H
#ifdef __cplusplus
 extern "C" {
#endif
	 
#include "main.h"


// mode
// #define HARD_SPI
// #define GPIO_SIMU_SPI
// #define HARD_IIC
#define GPIO_SIMU_IIC


// 7pin SPI Info
// D0(SCK)			[ ]
// D1(DATA)			[ ]
// RES(reset)		[ ]
// DC(0-cmd/1-dat)	[ ]
// CS(Ƭѡ)			[ ]

// gpio
#if defined(HARD_SPI) || defined(GPIO_SIMU_SPI)

#ifdef GPIO_SIMU_SPI
// #define OLED_D0(x)	(x ?HAL_GPIO_WritePin(OLED_D0_GPIO_Port, OLED_D0_Pin, GPIO_PIN_SET)		\
// 						:HAL_GPIO_WritePin(OLED_D0_GPIO_Port, OLED_D0_Pin, GPIO_PIN_RESET))

// #define OLED_D1(x)	(x ?HAL_GPIO_WritePin(OLED_D1_GPIO_Port, OLED_D1_Pin, GPIO_PIN_SET)		\
// 						:HAL_GPIO_WritePin(OLED_D1_GPIO_Port, OLED_D1_Pin, GPIO_PIN_RESET)
#endif

// #define OLED_RES(x)	(x ?HAL_GPIO_WritePin(OLED_RES_GPIO_Port, OLED_RES_Pin, GPIO_PIN_SET)	\
// 						:HAL_GPIO_WritePin(OLED_RES_GPIO_Port, OLED_RES_Pin, GPIO_PIN_RESET))

// #define OLED_DC(x)	(x ?HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, GPIO_PIN_SET)		\
// 						:HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, GPIO_PIN_RESET))

// #define OLED_CS(x)	(x ?HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, GPIO_PIN_SET)		\
// 						:HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, GPIO_PIN_RESET))

#endif

#if defined(HARD_IIC) || defined(GPIO_SIMU_IIC)

#ifdef GPIO_SIMU_IIC	// SCL SDA 均为开漏模式
#define OLED_SCL(x)	(x ?HAL_GPIO_WritePin(OLED_SCL_GPIO_Port, OLED_SCL_Pin, GPIO_PIN_SET)		\
						:HAL_GPIO_WritePin(OLED_SCL_GPIO_Port, OLED_SCL_Pin, GPIO_PIN_RESET))

#define OLED_SDA(x) (x ?HAL_GPIO_WritePin(OLED_SDA_GPIO_Port, OLED_SDA_Pin, GPIO_PIN_SET)		\
						:HAL_GPIO_WritePin(OLED_SDA_GPIO_Port, OLED_SDA_Pin, GPIO_PIN_RESET))
#endif

#define OLED_READ_SDA() (HAL_GPIO_ReadPin(OLED_SDA_GPIO_Port, OLED_SDA_Pin))

#define SDA_IN()	do{										\
	GPIO_InitTypeDef GPIO_InitStruct = {0};					\
	GPIO_InitStruct.Pin = OLED_SDA_Pin;						\
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;					\
	GPIO_InitStruct.Pull = GPIO_NOPULL;						\
	HAL_GPIO_Init(OLED_SDA_GPIO_Port, &GPIO_InitStruct);	\
}while(0)

#define SDA_OUT()	do{										\
	GPIO_InitTypeDef GPIO_InitStruct = {0};					\
	GPIO_InitStruct.Pin = OLED_SDA_Pin;						\
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;				\
	GPIO_InitStruct.Pull = GPIO_NOPULL;						\
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;		\
	HAL_GPIO_Init(OLED_SDA_GPIO_Port, &GPIO_InitStruct);	\
}while(0)

#endif


// OLED Info
#define OLED_WIDTH		(128)
#define OLED_HEIGHT		(64)
#define OLeD_PAGE 		(8)
#define OLED_BRIGHTNESS	(0xCF)


// Function Def

#if defined(HARD_IIC) || defined(GPIO_SIMU_IIC)
static void IIC_Start();
static void IIC_Stop();
static uint8_t IIC_Wait_Ask(); // 0:answer error 1:answer ok
#endif

static void OLED_WByte(uint8_t data);
static void OLED_WDat(uint8_t dat);
static void OLED_WCmd(uint8_t cmd);
static void OLED_RefreshGRAM(void);
static void OLED_DrawPoint(uint8_t x, uint8_t y, uint8_t t);

void OLED_Init(void);
void OLED_Fill(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t dot);
void OLED_CLS(void);

static void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size, uint8_t mode);
//static uint32_t myPow(uint8_t m, uint8_t n);

void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size);
void OLED_ShowString(uint8_t x, uint8_t y, const uint8_t *p, uint8_t size);
	
#ifdef __cplusplus
}
#endif
#endif /* __OLED_H */
